using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Text;
using System.Linq;
using MICZ.CodeBuilder.IRepository.SqlSugar;
using MICZ.CodeBuilder.ViewModels.PageData;
using MICZ.CodeBuilder.Commons.ExpressionExtensions;
using System.IO;
using RazorEngine;
using RazorEngine.Templating;
using MICZ.CodeBuilder.IService;
using MICZ.CodeBuilder.Commons.FileHelper;
using MICZ.CodeBuilder.ViewModels;
using System.Web;

namespace MICZ.CodeBuilder.Service.Project
{
    /// <summary>
    /// 项目服务层
    /// </summary>
    public class ProjectService : IProjectService
    {
        private static string CodeTemplate = Path.Combine(Directory.GetCurrentDirectory(), @"CodeTemplate");
        private static string CodeBuilder = Path.Combine(Directory.GetCurrentDirectory(), @"CodeBuilder");
        private static string TemplateName = "MICZTemplate";

        ISqlSugarRepository SqlSugarRepository;
        public ProjectService(ISqlSugarRepository _SqlSugarRepository)
        {
            SqlSugarRepository = _SqlSugarRepository;
        }
        #region 项目
        /// <summary>
        /// 模板创建
        /// </summary>
        /// <param name="TemplateFileName">模板名称(Controller)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async Task<string> ControllerTemplateCode(string TemplateFileName, BuilderTableViewModel obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            return Engine.Razor.RunCompile(Template, TemplateName+"_" + Guid.NewGuid(), null, obj);
        }

        /// <summary>
        /// 生成代码保存到CodeBuilder
        /// </summary>
        /// <param name="Projectname">项目命名空间名称</param>
        /// <param name="TemplateFileName">模板名称(Controller)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async void ControllerTemplateCreate(string TemplateFileName, BuilderTableViewModel obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            string Result= HttpUtility.HtmlDecode(Engine.Razor.RunCompile(Template, TemplateName + "_" + Guid.NewGuid(), null, obj));
            var projectDic = CodeBuilder + "\\" + obj.Namespace+"."+ TemplateFileName + "\\";
            var projectFile = projectDic+"\\Controllers"+"\\"+obj.TableName + TemplateFileName +".cs";
            //var projectFile = projectDic+"\\"+obj.TableName + TemplateFileName +".cs";
            if (!FileHelper.IsExistDirectory(projectDic))
            {
                FileHelper.CreateDirectory(projectDic);
            }
            if (FileHelper.IsExistFile(projectFile))
                FileHelper.DeleteFile(projectFile);
            FileHelper.CreateFile(projectFile, Result, System.Text.Encoding.UTF8);
        }
        
        /// <summary>
        /// 模板创建
        /// </summary>
        /// <param name="TemplateFileName">模板名称(Service,AppService)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async Task<string> TemplateCode(string TemplateFileName, BuilderTableViewModel obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            return Engine.Razor.RunCompile(Template, TemplateName+"_" + Guid.NewGuid(), null, obj);
        }

        /// <summary>
        /// 生成代码保存到CodeBuilder
        /// </summary>
        /// <param name="Projectname">项目命名空间名称</param>
        /// <param name="TemplateFileName">模板名称(Service,AppService)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async void TemplateCreate(string TemplateFileName, BuilderTableViewModel obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            string Result= HttpUtility.HtmlDecode(Engine.Razor.RunCompile(Template, TemplateName + "_" + Guid.NewGuid(), null, obj));
            var projectDic = CodeBuilder + "\\" + obj.Namespace+"."+ TemplateFileName + "\\";
            //var projectFile = projectDic+"\\"+obj.TableName + TemplateFileName +".cs";
            string projectFile = "";
            if (TemplateFileName.StartsWith("I"))
                projectFile = projectDic + "\\I" + obj.TableName + TemplateFileName.Remove(0,1) + ".cs";
            else
                projectFile = projectDic + "\\" + obj.TableName + TemplateFileName + ".cs";
            if (!FileHelper.IsExistDirectory(projectDic))
            {
                FileHelper.CreateDirectory(projectDic);
            }
            if (FileHelper.IsExistFile(projectFile))
                FileHelper.DeleteFile(projectFile);
            FileHelper.CreateFile(projectFile, Result, System.Text.Encoding.UTF8);
        }

        /// <summary>
        /// Repository模板创建
        /// </summary>
        /// <param name="TemplateFileName">模板名称(Repository)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async Task<string> RepositoryTemplateCode(string TemplateFileName, List<BuilderTableViewModel> obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            return Engine.Razor.RunCompile(Template, TemplateName+"_" + Guid.NewGuid(), null, obj);
        }

        /// <summary>
        /// Repository层生成代码保存到CodeBuilder
        /// </summary>
        /// <param name="Projectname">项目命名空间名称</param>
        /// <param name="TemplateFileName">模板名称(Repository)</param>
        /// <param name="obj">生成对象</param>
        /// <returns></returns>
        public async void RepositoryTemplateCreate(string TemplateFileName, List<BuilderTableViewModel> obj)
        {
            string Template = await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TemplateFileName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            string Result= HttpUtility.HtmlDecode(Engine.Razor.RunCompile(Template, TemplateName + "_" + Guid.NewGuid(), null, obj));
            var projectDic = CodeBuilder + "\\" + obj[0].Namespace+"."+ TemplateFileName + "\\";
            var projectFile = projectDic+"\\"+ TemplateFileName +".cs";
            if (!FileHelper.IsExistDirectory(projectDic))
            {
                FileHelper.CreateDirectory(projectDic);
            }
            if (FileHelper.IsExistFile(projectFile))
                FileHelper.DeleteFile(projectFile);
            FileHelper.CreateFile(projectFile, Result, System.Text.Encoding.UTF8);
        }

        /// <summary>
        /// 生成Model
        /// </summary>
        /// <param name="Projectname">项目命名空间名称</param>
        /// <param name="obj">生成对象(列表)</param>
        /// <param name="Type">Model类型:1Model2ViewModel</param>
        /// <returns></returns>
        public async Task<string> TemplateModel(string Projectname, List<BuilderColumnViewModel> obj, int Type = 1)
        {
            string TypeName = "Model";
            if (Type == 2)
            {
                TypeName = "ViewModel";
            }
            string Template =await System.IO.File.ReadAllTextAsync(Path.Combine(CodeTemplate, TypeName + ".cs"), System.Text.Encoding.UTF8);
            //Result = Engine.Razor.RunCompile(template, "MICZTemplate", null, new { TableName = item.Name });
            return Engine.Razor.RunCompile(Template, TemplateName + "_" + Guid.NewGuid(), null, obj);
        }
        
        /// <summary>
        /// 生成Model保存到CodeBuilder
        /// </summary>
        /// <param name="Projectname">项目命名空间名称</param>
        /// <param name="Type">Model类型:1Model2ViewModel</param>
        /// <returns></returns>
        public async void ModelCreate(string Projectname, int Type = 1)
        {
            await Task.Run(() =>
            {
                string projectDic;
                string TypeName = "Model";
                if (Type == 2)
                    TypeName = "ViewModel";               
                projectDic = CodeBuilder + "\\" + Projectname + "." + TypeName + "\\";
                if (!FileHelper.IsExistDirectory(projectDic))
                    FileHelper.CreateDirectory(projectDic);
                var css = Directory.GetFiles(projectDic).Where(it => it.Contains(".cs")&&!it.Contains(".csproj"));//查找实体.cs文件
                foreach (var item in css)
                {
                    FileHelper.DeleteFile(item);//循环删除
                }
                SqlSugarRepository.Db.MappingTables.Clear();//清楚映射
                if (Type == 2)
                {
                    foreach (var item in SqlSugarRepository.Db.DbMaintenance.GetTableInfoList(false))
                    {
                        string entityName = item.Name + TypeName;/*实体名大写*/
                        SqlSugarRepository.Db.MappingTables.Add(entityName, item.Name);
                        //foreach (var col in SqlSugarRepository.Db.DbMaintenance.GetColumnInfosByTableName(item.Name))
                        //{
                        //    SqlSugarRepository.Db.MappingColumns.Add(col.DbColumnName.ToUpper() /*类的属性大写*/, col.DbColumnName, entityName);
                        //}
                    }
                    SqlSugarRepository.Db.DbFirst.IsCreateAttribute().IsCreateDefaultValue().CreateClassFile(projectDic, Projectname + "." + TypeName + "");
                }
                else
                    SqlSugarRepository.Db.DbFirst.IsCreateAttribute().IsCreateDefaultValue().CreateClassFile(projectDic, Projectname + "." + TypeName + "");
                //SqlSugarRepository.Db.DbFirst.SettingClassTemplate(old => { return old; })
                //.SettingNamespaceTemplate(old => { return old+ TypeName; })//命名空间
                //.CreateClassFile(projectDic, Projectname + "." + TypeName + "");
                //if (Type == 2)
                //{
                //    var Filecs = Directory.GetFiles(projectDic).Where(a=> Path.GetExtension(a).ToLower()==".cs");
                //    foreach (var item in Filecs)
                //    {
                //        if (File.Exists(item.Replace(".cs", "ViewModel.cs")))
                //            File.Delete(item.Replace(".cs", "ViewModel.cs"));
                //        File.Move(item, item.Replace(".cs", "ViewModel.cs"), true);
                //    }
                //}
            });
        }

        /// <summary>
        /// 创建WebApi项目(.csproj)自动添加到sln解决方案
        /// </summary>
        /// <param name="name">项目名称(包含命名空间)</param>
        public async void WebApiCreateProject(string name)
        {
            await Task.Run(() =>
            {
                Dictionary<string, string> ProjectIds = new Dictionary<string, string>();
                var templatePath = CodeTemplate + "/WebProject.txt";
                string projectId = Guid.NewGuid().ToString();
                string project = System.IO.File.ReadAllText(templatePath, System.Text.Encoding.UTF8).Replace("@pid", projectId).Replace("@AssemblyName", name); //从文件中读出模板内容
                var projectPath = CodeBuilder + "\\" + name + "\\" + name + ".csproj";
                var projectDic = CodeBuilder + "\\" + name + "\\";
                var binDic = CodeBuilder + "\\" + name + "\\bin";
                //if (!FileHelper.IsExistFile(projectPath))
                //{
                if (!FileHelper.IsExistDirectory(projectDic))
                {
                    FileHelper.CreateDirectory(projectDic);
                }
                if (!FileHelper.IsExistDirectory(binDic))
                {
                    FileHelper.CreateDirectory(binDic);
                }
                if (FileHelper.IsExistFile(projectPath))
                    FileHelper.DeleteFile(projectPath); 
                FileHelper.CreateFile(projectPath, project, System.Text.Encoding.UTF8);
                //FileHelper.CreateFile(projectDic + "\\class1.cs", "", System.Text.Encoding.UTF8);
                if (FileHelper.IsExistFile(projectDic + "packages.config"))
                    FileHelper.DeleteFile(projectDic + "packages.config");
                File.Copy(CodeTemplate + "/nuget.txt", projectDic + "packages.config");
                ProjectIds.Add(name, projectId);
                AppendProjectToSln(projectId, name);
                //}
            });
        }
        
        /// <summary>
        /// 创建项目(.csproj)自动添加到sln解决方案
        /// </summary>
        /// <param name="name">项目名称(包含命名空间)</param>
        public async void CreateProject(string name)
        {
            await Task.Run(() =>
            {
                Dictionary<string, string> ProjectIds = new Dictionary<string, string>();
                var templatePath = CodeTemplate + "/Project.txt";
                string projectId = Guid.NewGuid().ToString();
                string project = System.IO.File.ReadAllText(templatePath, System.Text.Encoding.UTF8).Replace("@pid", projectId).Replace("@AssemblyName", name); //从文件中读出模板内容
                var projectPath = CodeBuilder + "\\" + name + "\\" + name + ".csproj";
                var projectDic = CodeBuilder + "\\" + name + "\\";
                var binDic = CodeBuilder + "\\" + name + "\\bin";
                //if (!FileHelper.IsExistFile(projectPath))
                //{
                if (!FileHelper.IsExistDirectory(projectDic))
                {
                    FileHelper.CreateDirectory(projectDic);
                }
                if (!FileHelper.IsExistDirectory(binDic))
                {
                    FileHelper.CreateDirectory(binDic);
                }
                if (FileHelper.IsExistFile(projectPath))
                    FileHelper.DeleteFile(projectPath); 
                FileHelper.CreateFile(projectPath, project, System.Text.Encoding.UTF8);
                //FileHelper.CreateFile(projectDic + "\\class1.cs", "", System.Text.Encoding.UTF8);
                if (FileHelper.IsExistFile(projectDic + "packages.config"))
                    FileHelper.DeleteFile(projectDic + "packages.config");
                File.Copy(CodeTemplate + "/nuget.txt", projectDic + "packages.config");
                ProjectIds.Add(name, projectId);
                AppendProjectToSln(projectId, name);
                //}
            });
        }

        /// <summary>
        /// 添加项目引用到解决方案(.sln)
        /// </summary>
        /// <param name="projectId">项目id</param>
        /// <param name="projectName">项目名称</param>
        public async void AppendProjectToSln(string projectId, string projectName)
        {
            await Task.Run(() =>
            {
                var slns = Directory.GetFiles(CodeBuilder).Where(it => it.Contains(".sln"));
                if (!slns.Any())
                {
                    string Text = System.IO.File.ReadAllText(CodeTemplate + "/Addsln.txt", System.Text.Encoding.UTF8);
                    #region 移除项目名称最后一项创建sln解决方案
                    List<string> lssln = projectName.Split(".").ToList();
                    lssln.Remove(lssln.Last());
                    FileHelper.CreateFile(CodeBuilder + "\\" +string.Join(".", lssln) + ".sln", Text, System.Text.Encoding.UTF8);
                    #endregion
                    slns = Directory.GetFiles(CodeBuilder).Where(it => it.Contains(".sln"));//重置查询sln文件
                }
                if (slns.Any())
                {
                    var sln = slns.First();
                    #region 判断项目是否存在
                    string slnText= File.ReadAllText(sln, System.Text.Encoding.UTF8);
                    if (slnText.Contains(projectName))
                        return;
                    #endregion
                    var templatePath = CodeTemplate + "/sln.txt";
                    string appendText = System.IO.File.ReadAllText(templatePath, System.Text.Encoding.UTF8)
                        .Replace("@pid", projectId)
                        .Replace("@name", projectName)
                        .Replace("@sid", Guid.NewGuid().ToString());
                    FileStream fs = new FileStream(sln, FileMode.Append);
                    var sw = new StreamWriter(fs);
                    sw.WriteLine(appendText);
                    sw.Close();
                    fs.Close();
                }
            });
        }

        /// <summary>
        /// 修改解决方案
        /// </summary>
        /// <param name="solutionName">解决方案名称</param>
        public async void RenameSln(string solutionName)
        {
            await Task.Run(() =>
            {
                var slns = Directory.GetFiles(CodeBuilder).Where(it => it.Contains(".sln"));
                if (slns.Any())
                {
                    File.Move(slns.First(), CodeBuilder + "\\" + solutionName + ".sln");
                }
            });
        }
        #endregion
    }


}
